<?php

namespace DataCube\DataCubeAggregation\Functions\MachineLearning\NeuralNetwork;

use DataCube\DataCubeAggregation\Exception\CustomException;

trait OptimizersTraits
{
    public function rubixOptimizerArrConvertor(array $customOptimizer, $disableDefaultThrows = true)
    {
        switch ($customOptimizer[0]) {
            case 'AdaGrad':
                $rate = empty($customOptimizer[1]) ? 0.01 : floatval($customOptimizer[1]);
                return new \Rubix\ML\NeuralNet\Optimizers\AdaGrad($rate);
            case 'AdaMax':
                $rate = empty($customOptimizer[1]) ? 0.001 : floatval($customOptimizer[1]);
                $momentumDecay = empty($customOptimizer[2]) ? 0.1 : floatval($customOptimizer[2]);
                $normDecay = empty($customOptimizer[3]) ? 0.001 : floatval($customOptimizer[3]);
                return new \Rubix\ML\NeuralNet\Optimizers\AdaMax($rate, $momentumDecay, $normDecay);
            case 'Momentum':
                $rate = empty($customOptimizer[1]) ? 0.001 : floatval($customOptimizer[1]);
                $decay = empty($customOptimizer[2]) ? 0.1 : floatval($customOptimizer[2]);
                $lookahead = !empty($customOptimizer[3]) && boolval($customOptimizer[3]);
                return new \Rubix\ML\NeuralNet\Optimizers\Momentum($rate, $decay, $lookahead);
            case 'RMSProp':
                $rate = empty($customOptimizer[1]) ? 0.001 : floatval($customOptimizer[1]);
                $decay = empty($customOptimizer[2]) ? 0.1 : floatval($customOptimizer[2]);
                return new \Rubix\ML\NeuralNet\Optimizers\RMSProp($rate, $decay);
            case 'StepDecay':
                $rate = empty($customOptimizer[1]) ? 0.01 : floatval($customOptimizer[1]);
                $losses = empty($customOptimizer[2]) ? 100 : intval($customOptimizer[2]);
                $decay = empty($customOptimizer[3]) ? 1e-3 : floatval($customOptimizer[3]);
                return new \Rubix\ML\NeuralNet\Optimizers\StepDecay($rate, $losses, $decay);
            case 'Stochastic':
                $rate = empty($customOptimizer[1]) ? 0.01 : floatval($customOptimizer[1]);
                return new \Rubix\ML\NeuralNet\Optimizers\Stochastic($rate);
            case 'Adam':
            default:
                if (!$disableDefaultThrows) {
                    throw new CustomException('Can not find optimizer');
                }
                $rate = empty($customOptimizer[1]) ? 0.001 : floatval($customOptimizer[1]);
                $momentumDecay = empty($customOptimizer[2]) ? 0.01 : floatval($customOptimizer[2]);
                $normDecay = empty($customOptimizer[3]) ? 0.001 : floatval($customOptimizer[3]);
                return new \Rubix\ML\NeuralNet\Optimizers\Adam($rate, $momentumDecay, $normDecay);
        }
    }
}